﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using kegg_service;
using Excel = Microsoft.Office.Interop.Excel;
using System.Net;
using System.Xml;
using System.Runtime.InteropServices;
using System.Diagnostics;
using QuickGraph;
using QuickGraph.Algorithms;
using System.Runtime.Serialization.Formatters.Binary;
using MySql.Data.MySqlClient;

namespace BPP
{
    public partial class controller
    {

        public class pathway_search
        {
            static Form1 form = Form.ActiveForm as Form1;

            //get data from kegg
            //parametrs: function name, parametr array:  input element name, input element type, input element value 
            static string GetKeddData(string reaction, string ind)
            {
                //create document to return
                XmlDocument xmlDoc = new XmlDocument();

                //url of the service
                string url = "http://www.genome.jp/dbget-bin/www_bget?" + reaction;

                // used to build entire input
                StringBuilder sb = new StringBuilder();

                // used on each read operation
                byte[] buf = new byte[8192];

                // prepare the web page we will be asking for
                HttpWebRequest request = (HttpWebRequest)
                    WebRequest.Create(url);

                // execute the request
                HttpWebResponse response = (HttpWebResponse)
                    request.GetResponse();

                // we will read data via the response stream
                Stream resStream = response.GetResponseStream();

                string tempString = null;
                int count = 0;

                do
                {
                    // fill the buffer with data
                    count = resStream.Read(buf, 0, buf.Length);

                    // make sure we read some data
                    if (count != 0)
                    {
                        // translate from bytes to ASCII text
                        tempString = Encoding.ASCII.GetString(buf, 0, count);

                        // continue building the string
                        sb.Append(tempString);
                    }
                }
                while (count > 0); // any more data to read?


                string s = sb.ToString();

                string rpair_st = "";
                List<string> rpair = new List<string>();

                string[] tmp1 = s.Split(new string[] { "<tr>" }, StringSplitOptions.None);

                foreach (string aaa in tmp1)
                {
                    if (aaa.Contains("<nobr>Equation</nobr>"))
                    {
                        //string[] r = aaa.Split(new string[] { "\">", "</a>", "<a href" }, StringSplitOptions.RemoveEmptyEntries);
                        //foreach (string tmp in r)
                        //{
                        //    if (!tmp.StartsWith("=") && !tmp.StartsWith("<"))
                        //        equation = equation + " " + tmp;
                        //}
                        //equation = equation.Replace("&lt;", "<");
                    }

                    if (aaa.Contains("<nobr>Definition</nobr>"))
                    {

                    }
                    if (aaa.Contains("<nobr>Name</nobr>"))
                    {

                    }
                    if (aaa.Contains("\">RP") && !aaa.Contains("leave") && !aaa.Contains("trans"))
                    {
                        //aaa.Contains("main") &&
                        if (aaa.Contains(ind.Substring(5)))
                        {
                            string tmp3 = aaa.Remove(0, aaa.IndexOf("left\">C") + 6);
                            tmp3 = tmp3.Remove(14);
                            rpair.Add(tmp3);

                            Write_Reaction_Compounds3(reaction, "cpd:" + tmp3.Substring(0, 6));
                            Write_Reaction_Compounds3(reaction, "cpd:" + tmp3.Substring(7));

                            rpair_st = rpair_st + " " + "cpd:" + tmp3;
                            //rpair_st = "cpd:" + rpair_st;
                            //  rpair_st = rpair_st.Insert(rpair_st.IndexOf(" C"), "cpd:");
                            rpair_st = rpair_st.Insert(rpair_st.LastIndexOf("C"), "cpd:");
                            rpair_st = rpair_st.Trim();


                        }

                    }
                }
                // print out page source
                //  Console.WriteLine(equation);
                return rpair_st;
            }


            public static void FindReactions(string source, string product)
            {
                form.label6.Text = "reactions by compound 1";
                

                form.Refresh();
                List<List<string>> new_compounds = new List<List<string>>();
                
                List<string> listOfCompoundsFilled = new List<string>();
                listOfCompoundsFilled.Add(source);

                new_compounds.Add(listOfCompoundsFilled);

                for (int ix = 0; ix < int.Parse(form.txtLevel.Text); ix++)
                {
                    form.label8.Text = "level" + ix;
                    new_compounds = Fill_Vertex(new_compounds);
                    

                }
                SearchPath();



                form.label6.Text = "finish";
                form.Refresh();

                //Func<IEdge<object>, double> edgeCost = e => 1; // constant cost

                //byte[] a = shared_functions.ObjectToByteArray((object)shared_functions.h);
                //File.WriteAllBytes("graph.txt", a);

            }

            private static void SearchPath()
            {
                Func<IEdge<object>, double> edgeCost = eg => 1; // constant cost



              //  int pathCount = int.Parse(form.textBox1.Text);
                int threshold = int.Parse(form.txtTreshhold.Text); 

                int counter = 0;
                BidirectionalGraph<object, IEdge<object>> paths = new BidirectionalGraph<object, IEdge<object>>();

                //ne scital vse elementi
                //TODDO
                //nado scitatj kuda to vse elementi kotorie ovoti=orjatusa v modeli i v naidennih kompoundah. dlja kazdogo iz nih vivesti puti kotorie vozmozhni.
                foreach (string verticle in controller.shared_functions.constructed_graph.Vertices)
                {
                    if (!verticle.Contains("rn:") && controller.shared_functions.model_graph.Vertices.Contains<object>(verticle))
                    {

                        int possible_path_count = controller.shared_functions.constructed_graph.Edges.Count<IEdge<object>>(o => o.Source.ToString() == verticle );


                        //set pathway max count
                        if (int.Parse(form.txtPatwayCount.Text) < possible_path_count)
                        {
                            possible_path_count = int.Parse(form.txtPatwayCount.Text);
                        }

                            //get all paths between 2 elements
                            foreach (IEnumerable<IEdge<object>> path in
                                controller.shared_functions.constructed_graph.RankedShortestPathHoffmanPavley<object, IEdge<object>>(
                                    edgeCost, "cpd:" + form.comboBox1.SelectedItem.ToString().Substring(0, 6), verticle, possible_path_count))
                            {
                                if (path.Count<object>() <= threshold)
                                {
                                    counter++;

                                    string s = "";
                                    foreach (var edges in path)
                                    {
                                        s = s + " " + edges;

                                        ///dobavitj v fail modeli eti dannie
                                        paths.AddVerticesAndEdge(new Edge<object>(edges.Source, edges.Target));
                                    }

                                    form.listBox1.Items.Add(s);
                                }

                            }
                        

                    }
                }

            }

            private static List<List<string>> Fill_Vertex( List<List<string>> compounds)
            {
               // List<List<string>> new_compounds = new List<List<string>>();

                List<string> new_compound_line = new List<string>();

                
                    int count = compounds[compounds.Count - 1].Count;
                    form.label9.Text = count.ToString();


                 foreach (string st in compounds[compounds.Count-1])
                 {
                    count = count - 1;
                    form.label9.Text = count.ToString();


                    List<string> list_of_reactions_by_compound = new List<string>();
                    List<List<string>> list_of_compounds_by_reaction3 = new List<List<string>>();
                   
                    
                   

                    list_of_reactions_by_compound = Find_Reactions_By_Compound(st);


                    //prosmotretj etu funkciju
                    list_of_compounds_by_reaction3 = Find_Compounds_By_Reaction2(list_of_reactions_by_compound, st);



                    IEdge<object> edge;

                    //if (form.listBox1.Items.Count < int.Parse(form.txtPatwayCount.Text))
                    //{

                        foreach (List<string> list in list_of_compounds_by_reaction3)
                        {
                            try
                            {

                                if (list.Count > 1)
                                {
                                    for (int i = 0; i < list.Count - 1; i++)
                                    {

                                        //zdesj vozmozhna owibka

                                        Metabolites met = null;

                                        //if (list[i] != st)
                                        //{
                                        //    met = controller.read_model.listOfMetabolites.Find(o => o.KEGG_ID == list[i].Substring(4));

                                        //    if (met != null)
                                        //    {
                                        //        form.listBox1.Items.Add(st + " -> " + list[list.Count - 1] + " -> " + list[i]);
                                        //    }
                                        //}

                                        form.Refresh();

                                        if (!new_compound_line.Contains(list[i]) && compounds.FindAll(o => o.Contains(list[i])).Count==0)
                                            new_compound_line.Add(list[i]);

                                        if (!shared_functions.constructed_graph.TryGetEdge(list[i], list[list.Count - 1], out edge))
                                            shared_functions.constructed_graph.AddVerticesAndEdge(new Edge<object>(list[i], list[list.Count - 1]));
                                        if (!shared_functions.constructed_graph.TryGetEdge(list[list.Count - 1], list[i], out edge))
                                            shared_functions.constructed_graph.AddVerticesAndEdge(new Edge<object>(list[list.Count - 1], list[i]));
                                    }
                                }
                            }
                            catch (Exception ex)
                            {

                            }
                        //}
                    }

                    
                }
                compounds.Add(new_compound_line);
               
                return compounds;
            }


            //read reactions by compound
            private static List<string> Find_Reactions_By_Compound(string source)
            {
                List<string> list_of_reactions_by_compound = new List<string>();



                form.label6.Text="find reaction by cmpound " +source;
                form.Refresh();
                list_of_reactions_by_compound = Read_Compound_Reactions(source);

                string[] get_reactions;

                //todo zdesj podpravitj cto bi ne bilo bi vsjakih herovin
                if (list_of_reactions_by_compound.Count == 0)
                {
                    get_reactions = shared_functions.kegg.get_reactions_by_compound(source);
                    string[] s = new string[25];
                    if (get_reactions.Length > 25)
                    {
                        for (int i = 0; i < 25; i++)
                            s[i] = get_reactions[i];
                        Write_Compound_Reacions(source, s);
                        list_of_reactions_by_compound = s.ToList<string>();
                    }
                    else
                    {
                        Write_Compound_Reacions(source, get_reactions);

                        list_of_reactions_by_compound = get_reactions.ToList<string>();
                    }

                    Console.WriteLine("read reactions");
                }
                return list_of_reactions_by_compound;
            }


            //read compounds by reaction
            private static List<List<string>> Find_Compounds_By_Reaction2(List<string> list_of_reactions_by_compound, string compound)
            {
                List<string> list_of_compounds_by_reaction = new List<string>();

                List<List<string>> list = new List<List<string>>();

                form.label6.Text = "find cmpound by  reaction" + compound;
                form.Refresh();
                list.Clear();
                list_of_compounds_by_reaction.Clear();

                foreach (string reaction in list_of_reactions_by_compound)
                {
                    list_of_compounds_by_reaction = Read_Reaction_Compound(reaction);

                    if (list_of_compounds_by_reaction.Count == 0)
                    {
                        //sdelatj zapis v bazu
                        string comp = GetKeddData(reaction, compound);

                        string[] tmp = comp.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);

                        List<string> tmp3 = new List<string>();

                        foreach (string s in tmp)
                        {
                            string[] tmp1 = s.Split(new string[] { "_" }, StringSplitOptions.RemoveEmptyEntries);

                            foreach (string s1 in tmp1)
                            {
                                // && s1 != compound
                                if (s.Contains(compound))
                                {
                                    tmp3.Add(s1);
                                }
                            }
                        }

                        list_of_compounds_by_reaction = tmp3;

                        Console.WriteLine("read compounds");
                    }

                    list_of_compounds_by_reaction.Add(reaction);
                    list.Add(list_of_compounds_by_reaction);
                }
                return list;
            }


            //writes reactions
            private static void Write_Compound_Reacions(string _object, string[] _object_list)
            {

                form.label6.Text = "write cmpound to db" + _object;
                form.Refresh();

                string MyConString = "SERVER=localhost;DATABASE=pathfinder;UID=root;PASSWORD=123;";

                MySqlConnection connection = new MySqlConnection(MyConString);
                MySqlCommand command = connection.CreateCommand();

                try
                {
                    connection.Open();

                    foreach (string s in _object_list)
                    {
                        command.CommandText = "insert into compound_reaction (compound, reaction) values ('" + _object + "', '" + s + "')";
                        command.ExecuteScalar();
                    }

                    connection.Close();
                }
                catch (MySqlException ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            }

            private static void Write_Reaction_Compounds3(string _object, string _object_list)
            {

                form.label6.Text = "write reactions to db" + _object;
                form.Refresh();
                string MyConString = "SERVER=localhost;DATABASE=pathfinder;UID=root;PASSWORD=123;";

                MySqlConnection connection = new MySqlConnection(MyConString);
                MySqlCommand command = connection.CreateCommand();

                try
                {
                    connection.Open();
                    command.CommandText = "insert into reaction_compound (reaction, compound) values ('" + _object + "', '" + _object_list + "')";
                    command.ExecuteScalar();
                    connection.Close();
                }
                catch (MySqlException ex)
                {
                    MessageBox.Show(ex.ToString());
                }

               
            }

          

            private static List<string> Read_Compound_Reactions(string compound)
            {
                string MyConString = "SERVER=localhost;DATABASE=pathfinder;UID=root;PASSWORD=123;";

                List<string> list = new List<string>();

                form.label6.Text = "read cmpound reactions" + compound;
                form.Refresh();
                MySqlConnection connection = new MySqlConnection(MyConString);
                MySqlCommand command = connection.CreateCommand();
                MySqlDataReader reader;

                command.CommandText = "select * from compound_reaction where compound ='" + compound + "'";

                try
                {
                    connection.Open();
                    reader = command.ExecuteReader();
                    int i = 0;
                    while (reader.Read())
                    {
                        if (i < 30)
                            list.Add(reader.GetValue(2).ToString());
                    }

                    connection.Close();
                }
                catch (MySqlException ex)
                {
                    MessageBox.Show(ex.ToString());
                   
                }

               

                return list;
            }

            //retur rpair list
            private static List<string> Read_Reaction_Compound(string reaction)
            {
                string MyConString = "SERVER=localhost;DATABASE=pathfinder;UID=root;PASSWORD=123;";

                List<string> list = new List<string>();

                form.label6.Text = "read reactions cmpound " + reaction;
                form.Refresh();

                MySqlConnection connection = new MySqlConnection(MyConString);
                MySqlCommand command = connection.CreateCommand();
                MySqlDataReader reader;

                command.CommandText = "select * from reaction_compound where reaction ='" + reaction + "'";


                try
                {
                    connection.Open();

                    reader = command.ExecuteReader();

                    while (reader.Read())
                    {
                        list.Add(reader.GetValue(2).ToString());
                    }

                    connection.Close();
                }
                catch(MySqlException ex)
                {

                    MessageBox.Show(ex.ToString());
                  
                }

                return list;
            }


            private static bool Check_Compound_In_Database(string compound)
            {
                string MyConString = "SERVER=localhost;DATABASE=pathfinder;UID=root;PASSWORD=123;";

                MySqlConnection connection = new MySqlConnection(MyConString);
                MySqlCommand command = connection.CreateCommand();
                MySqlDataReader reader;
  bool result = false;
                command.CommandText = "select * from compound_reaction where compound ='" + compound + "'";
                
                try{

                        connection.Open();
                        reader = command.ExecuteReader();

                      

                        if (reader.HasRows)
                        {
                            result = true;
                        }

                        connection.Close();

                }
                catch(MySqlException ex)
                {

                    MessageBox.Show(ex.ToString());
                  
                }

                return result;
            }

            private static bool Check_Reaction_In_Database(string reaction)
            {
                string MyConString = "SERVER=localhost;DATABASE=pathfinder;UID=root;PASSWORD=123;";

                MySqlConnection connection = new MySqlConnection(MyConString);
                MySqlCommand command = connection.CreateCommand();
                MySqlDataReader reader;
                 bool result = false;
                command.CommandText = "select * from reaction_compound where compound ='" + reaction + "'";
                try
                {
                    connection.Open();
                    reader = command.ExecuteReader();
                    if (reader.HasRows)
                    {
                        result = true;
                    }

                    connection.Close();
                }
                catch(MySqlException ex)
                {

                    MessageBox.Show(ex.ToString());
                  
                }

                return result;
            }

        }       
    }
}





